package com.jic.market.impl.rest.discount;

import com.jic.market.common.exception.MarketErrorCodeEnum;
import com.jic.market.common.exception.MarketException;
import com.jic.market.enums.DiscountAmountServiceOperateEnum;
import com.jic.market.enums.FrontPromotionTypeEnum;
import com.jic.market.impl.rest.discount.model.ConditionDiscountModel;
import com.jic.market.impl.rest.discount.model.GoodsDetailModel;
import com.jic.market.impl.rest.discount.model.ShareModel;
import com.jic.market.impl.rest.discount.processor.AbstractConditionDiscountProcessor;
import com.jic.market.impl.rest.discount.processor.AbstractSingleDiscountProcessor;
import com.jic.market.request.rest.discount.DiscountBaseRequest;
import com.jic.market.request.rest.discount.DiscountCancelRequest;
import com.jic.market.request.rest.discount.DiscountOrderPayRequest;
import com.jic.market.service.rest.discount.DiscountProcesserService;
import org.apache.commons.lang.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ApplicationObjectSupport;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author yinhaijun
 * @date: 2020/5/6
 */
@Service
public class DiscountProcesserServiceImpl extends ApplicationObjectSupport implements DiscountProcesserService {

    private static final HashMap<FrontPromotionTypeEnum, String> processorMap;

    /**
     * 服务启动的时候，会把所有的处理器的类名加载到processorMap中
     */
    static {
        processorMap = new HashMap<>();
        FrontPromotionTypeEnum[] values = FrontPromotionTypeEnum.values();
        for (FrontPromotionTypeEnum value : values) {
            if (null != value.getProcessor() && !value.getProcessor().equals("")) {
                processorMap.put(value, value.getProcessor());
            }
        }
    }

    @Override
    public AbstractConditionDiscountProcessor getConditionProcessor(FrontPromotionTypeEnum frontPromotionTypeEnum) {
        ApplicationContext applicationContext = getApplicationContext();
        String processorName = processorMap.get(frontPromotionTypeEnum);
        AbstractConditionDiscountProcessor discountProcessor = (AbstractConditionDiscountProcessor) applicationContext.getBean(processorName);
        return discountProcessor;
    }

    @Override
    public void processorPromotion(Map<String, GoodsDetailModel> goodsDetailModelMap, Object request, String thirdUserId, DiscountAmountServiceOperateEnum operateEnum) {
        if(null == goodsDetailModelMap || goodsDetailModelMap.isEmpty()){
            return;
        }
        goodsDetailModelMap.forEach((thirdSkuId, goodsDetailModel)->{
            ApplicationContext applicationContext = getApplicationContext();
            // 根据枚举获取对应的处理器的全类名
            String processorName = processorMap.get(goodsDetailModel.getFrontPromotionTypeEnum());
            if(StringUtils.isNotBlank(processorName)){
                // 根据全类名从Spring容器中获取到实例
                AbstractSingleDiscountProcessor singleDiscountProcessor = (AbstractSingleDiscountProcessor) applicationContext.getBean(processorName);
                // 根据操作类型枚举，选择调用哪一个方法
                if(DiscountAmountServiceOperateEnum.SHOPPING_CART_QUERY == operateEnum){
                    singleDiscountProcessor.queryShoppingCart(goodsDetailModel, (DiscountBaseRequest) request);
                }
                else if(DiscountAmountServiceOperateEnum.COUPON_QUERY == operateEnum){
                    singleDiscountProcessor.querySettlement(goodsDetailModel, (DiscountBaseRequest) request);
                }
                else if(DiscountAmountServiceOperateEnum.SETTLEMENT_QUERY == operateEnum){
                    singleDiscountProcessor.querySettlement(goodsDetailModel, (DiscountBaseRequest) request);
                }
                else if(DiscountAmountServiceOperateEnum.CREATE == operateEnum){
                    singleDiscountProcessor.create(goodsDetailModel, request, thirdUserId);
                }
                else if(DiscountAmountServiceOperateEnum.PAY == operateEnum){
                    singleDiscountProcessor.pay(goodsDetailModel, (DiscountOrderPayRequest) request);
                }
                else if(DiscountAmountServiceOperateEnum.REFUND == operateEnum){
                    singleDiscountProcessor.cancel(goodsDetailModel, request);
                }
            }
        });
    }

    @Override
    public void processorPromotion(List<ConditionDiscountModel> conditionDiscountModelList, Map<String, GoodsDetailModel> goodsDetailModelMap, Object request, DiscountAmountServiceOperateEnum operateEnum) {
        if(null != conditionDiscountModelList && !conditionDiscountModelList.isEmpty()) {
            // 获取Spring上下文
            ApplicationContext applicationContext = getApplicationContext();
            // 循环处理，之所以需要i--执行，是因为后面可坑会删除无优惠的模型
            for (int i = conditionDiscountModelList.size() -1; i>=0; i--) {
                // 获取对应的处理器全类名
                ConditionDiscountModel conditionDiscountModel = conditionDiscountModelList.get(i);
                String processorName = processorMap.get(conditionDiscountModel.getFrontPromotionTypeEnum());
                if(StringUtils.isNotBlank(processorName)){
                    // 获取 处理器
                    AbstractConditionDiscountProcessor conditionDiscountProcessor = (AbstractConditionDiscountProcessor) applicationContext.getBean(processorName);
                    if(DiscountAmountServiceOperateEnum.SHOPPING_CART_QUERY == operateEnum){
                        conditionDiscountProcessor.queryShoppingCart(conditionDiscountModel, goodsDetailModelMap, request);
                    }
                    else if(DiscountAmountServiceOperateEnum.COUPON_QUERY == operateEnum){
                        conditionDiscountProcessor.querySettlement(conditionDiscountModel, goodsDetailModelMap, request);
                    }
                    else if(DiscountAmountServiceOperateEnum.SETTLEMENT_QUERY == operateEnum){
                        conditionDiscountProcessor.querySettlement(conditionDiscountModel, goodsDetailModelMap, request);
                    }
                    else if(DiscountAmountServiceOperateEnum.CREATE == operateEnum){
                        conditionDiscountProcessor.create(conditionDiscountModel, goodsDetailModelMap, request);
                    }
                    else if(DiscountAmountServiceOperateEnum.PAY == operateEnum){
                        conditionDiscountProcessor.pay(conditionDiscountModel, goodsDetailModelMap, operateEnum, request);
                    }
                    else if(DiscountAmountServiceOperateEnum.REFUND == operateEnum){
                        conditionDiscountProcessor.cancel(conditionDiscountModel, goodsDetailModelMap, ((DiscountCancelRequest) request).getThirdProductCodeList(), request);
                    }
                }
                // 模型净化 去除一些未优惠的模型
                if(conditionDiscountModel.getFrontPromotionTypeEnum() == FrontPromotionTypeEnum.GIFT_FULL_QUOTA
                    || conditionDiscountModel.getFrontPromotionTypeEnum() == FrontPromotionTypeEnum.GIFT_FULL_NUM
                    || conditionDiscountModel.getFrontPromotionTypeEnum() == FrontPromotionTypeEnum.INCREASE_FULL_QUOTA
                    || conditionDiscountModel.getFrontPromotionTypeEnum() == FrontPromotionTypeEnum.INCREASE_FULL_NUM){
                    if(null == conditionDiscountModel.getGiftDetailList() || conditionDiscountModel.getGiftDetailList().isEmpty()){
                        conditionDiscountModelList.remove(i);
                        goodsDetailModelMap.forEach((thirdSkuId, goodsDetailModel)->{
                            Map<FrontPromotionTypeEnum, ShareModel> shareModelMap  = goodsDetailModel.getShareModelMap();
                            if(null != shareModelMap && !shareModelMap.isEmpty()){
                                ShareModel shareModel = shareModelMap.get(conditionDiscountModel.getFrontPromotionTypeEnum());
                                if(null != shareModel){
                                    shareModelMap.remove(conditionDiscountModel.getFrontPromotionTypeEnum());
                                }
                            }
                        });
                    }
                }

            }
        }
    }

    @Override
    public void couponQuery(List<ConditionDiscountModel> conditionDiscountModelList, Map<String, GoodsDetailModel> goodsDetailModelMap, Object request) {
        ApplicationContext applicationContext = getApplicationContext();
        String processorName = processorMap.get(FrontPromotionTypeEnum.COUPON_);
        AbstractConditionDiscountProcessor discountProcessor = (AbstractConditionDiscountProcessor) applicationContext.getBean(processorName);
        // 第一次循环，设置是否可用
        for (int i = conditionDiscountModelList.size() - 1; i >= 0; i--) {
            ConditionDiscountModel conditionDiscountModel = conditionDiscountModelList.get(i);
            AbstractConditionDiscountProcessor.ConditionResult conditionResult = discountProcessor.isCondition(conditionDiscountModel, goodsDetailModelMap, request, DiscountAmountServiceOperateEnum.COUPON_QUERY);
            conditionDiscountModel.getCouponInfo().setAvailableUse(conditionResult.getPass());
        }

        // 先按优先级排序，优惠劵的店铺劵优先于平台劵
        conditionDiscountModelList.sort(Comparator.comparing(ConditionDiscountModel::getSort));
        // 第二次循环，把可用的且选中的所对应的商品拿出来，如果其中有重复则报错
        List<String> selectedThirdSkuIdList = new ArrayList<>(); // 已被选中的优惠劵对应的商品
        for (int i = 0; i < conditionDiscountModelList.size(); i++) {
            ConditionDiscountModel conditionDiscountModel = conditionDiscountModelList.get(i);
            if (conditionDiscountModel.getCouponInfo().getSelected()) {
                List<String> thirdSkuIdList = conditionDiscountModel.getThirdSkuIdList();
                for (int j = thirdSkuIdList.size() - 1; j >= 0; j--) {
                    if (selectedThirdSkuIdList.contains(thirdSkuIdList.get(j))) {
                        throw new MarketException(MarketErrorCodeEnum.PARAM_ERROR, "当前被选中的优惠劵" + conditionDiscountModel.getCouponInfo().getCouponCode() + "与另一个有重复商品");
                    } else {
                        selectedThirdSkuIdList.add(thirdSkuIdList.get(j));
                    }
                }
            }
        }
        // 第三次循环移除对应的重复商品，也就是分组
        for (int i = 0; i < conditionDiscountModelList.size(); i++) {
            ConditionDiscountModel conditionDiscountModel = conditionDiscountModelList.get(i);
            if (!conditionDiscountModel.getCouponInfo().getSelected()) {
                List<String> thirdSkuIdList = conditionDiscountModel.getThirdSkuIdList();
                for (int j = thirdSkuIdList.size() - 1; j >= 0; j--) {
                    if (selectedThirdSkuIdList.contains(thirdSkuIdList.get(j))) {
                        thirdSkuIdList.remove(j);
                    } else {
                        selectedThirdSkuIdList.add(thirdSkuIdList.get(j));
                    }
                }
            }
        }

        // 第四次循环，设置是否可选，因为此时重复商品被移除了，计算结果会发生变动
        for (int i = conditionDiscountModelList.size() - 1; i >= 0; i--) {
            ConditionDiscountModel conditionDiscountModel = conditionDiscountModelList.get(i);
            AbstractConditionDiscountProcessor.ConditionResult conditionResult = discountProcessor.isCondition(conditionDiscountModel, goodsDetailModelMap, request, DiscountAmountServiceOperateEnum.COUPON_QUERY);
            conditionDiscountModel.getCouponInfo().setAvailableSelected(conditionResult.getPass());
        }
    }

    @Override
    public void couponProcess(List<ConditionDiscountModel> conditionDiscountModelList, Map<String, GoodsDetailModel> goodsDetailModelMap, Object request, DiscountAmountServiceOperateEnum operateEnum) {
        ApplicationContext applicationContext = getApplicationContext();
        String processorName = processorMap.get(FrontPromotionTypeEnum.COUPON_);
        AbstractConditionDiscountProcessor discountProcessor = (AbstractConditionDiscountProcessor) applicationContext.getBean(processorName);

        // 先按优先级排序，优惠劵的店铺劵优先于平台劵
        conditionDiscountModelList.sort(Comparator.comparing(ConditionDiscountModel::getSort));
        // 第二次循环，把可用的且选中的所对应的商品拿出来，如果其中有重复则报错
        List<String> selectedThirdSkuIdList = new ArrayList<>(); // 已被选中的优惠劵对应的商品
        // 第三次循环移除对应的重复商品，也就是分组
        for (int i = 0; i < conditionDiscountModelList.size(); i++) {
            ConditionDiscountModel conditionDiscountModel = conditionDiscountModelList.get(i);
            List<String> thirdSkuIdList = conditionDiscountModel.getThirdSkuIdList();
            for (int j = thirdSkuIdList.size() - 1; j >= 0; j--) {
                if (selectedThirdSkuIdList.contains(thirdSkuIdList.get(j))) {
                    throw new MarketException(MarketErrorCodeEnum.PARAM_ERROR, "当前优惠劵" + conditionDiscountModel.getCouponInfo().getCouponCode() + "与另一个有重复商品");
                } else {
                    selectedThirdSkuIdList.add(thirdSkuIdList.get(j));
                }
            }
        }

        for (int i = conditionDiscountModelList.size() - 1; i >= 0; i--) {
            ConditionDiscountModel conditionDiscountModel = conditionDiscountModelList.get(i);
            if (DiscountAmountServiceOperateEnum.SETTLEMENT_QUERY == operateEnum) {
                discountProcessor.querySettlement(conditionDiscountModel, goodsDetailModelMap, request);
            }
            if (DiscountAmountServiceOperateEnum.CREATE == operateEnum) {
                discountProcessor.create(conditionDiscountModel, goodsDetailModelMap, request);
            }
        }
    }

}
